package dico.game.wordFinder;

import java.awt.Point;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Stack;

import dico.finder.DicoAnalyser;
import dico.finder.Word;
import dico.finder.impl.SimpleWord;

public class GameGrid {
	/**
	 * the grid of char where we can find any word
	 */
	private char[][] char_grid;

	/**
	 * the dictionnary 
	 */
	private DicoAnalyser dictionary;

	/**
	 * all the word in the grid
	 */
	private List<Word> all_words;

	/**
	 * 
	 * @param width
	 * @param height
	 */
	public GameGrid(final int width, final int height, DicoAnalyser dictionnaire) {
		this.char_grid = new char[height][width];
		this.dictionary = dictionnaire;
		this.GenerateGrid();
	}

	/**
	 * generate the grod rin random
	 */
	private void GenerateGrid()
	{
		final int width = this.char_grid[0].length;
		final int height = this.char_grid.length;
		final Random random = new Random();

		for (int i = 0; i < width; i++) {
			for (int j = 0; j < height; j++) {
				final int rand = Math.abs(random.nextInt());
				this.char_grid[j][i] = (char) ((rand%(122-97))+97);
			}
		}
	}

	private void calculateAllWord(int begin_x, int begin_y) {
		/** travel all the array, to find a word */
		Stack<Object[]> a_visiter = new Stack<Object[]>();
		String current_word = "";
		List<Point> current_word_coord = new ArrayList<Point>();

		/** add the current char in the stack */
		a_visiter.push(new Object[] {0,new Point(begin_x, begin_y)});
		List<Word> words = null;
		while (!a_visiter.empty()) {
			/** get the last char and add his neighbours */
			Object[] current_coo = a_visiter.pop();
			Point point = (Point) current_coo[1];
			int current_word_size = (int) current_coo[0];
			/** add the char at the current word */
			int a_supprimer = current_word.length()-current_word_size;
			if (a_supprimer != 0)
				words = null;// a changer plus tard pour reprendre les aciennes listes de mots
			current_word = current_word.substring(0,current_word_size)+this.char_grid[(int) point.getY()][(int) point.getX()];
			for (int i = 0; i < a_supprimer; i++) {
				current_word_coord.remove(current_word_coord.size()-1);
			}
			current_word_coord.add(point);

			/** on va verifier que le mot a des mot commencant pas lui si non on peut tous simplement arreter la recherche ca ne sert plus a rien */
			if (words == null) {
				words = this.dictionary.getWordBeginBy(current_word);
			} else {
				words = DicoAnalyser.getWordBeginBy(words, current_word);
			}
			
			if (!words.isEmpty()) {
				final int word_size = current_word.length();
				if (this.dictionary.contains(current_word) && word_size > 2) {
					this.all_words.add(new SimpleWord(current_word, null));
				}

				for (int x = -1; x <= 1; x++) {
					for (int y = -1; y <= 1; y++) {
						final int this_x = (int) (point.getX()+x);
						final int this_y = (int) (point.getY()+y);
						Object[] current_cord = new Object[] {word_size,new Point(this_x,this_y)};
						if ((x != y || y != 0) // ne pas reprendre la case actuel
								&& this_y >= 0 && this_y < this.char_grid.length // verifier les bords
								&& this_x >= 0 && this_x < this.char_grid[0].length // verifier les bords
								&& !current_word_coord.contains(current_cord[1])
						) {
							a_visiter.push(current_cord);
						}
					}
				}
			}
		}
	}

	public List<Word> getAllWord() {
		if (all_words == null)	
			all_words = new LinkedList<Word>();
		for (int x = 0; x < this.char_grid[0].length; x++) {
			for (int y = 0; y < this.char_grid.length; y++) {
				System.out.println("CALCULE POUR : "+x+","+y+"==>"+all_words.size());
				this.calculateAllWord(x, y);
			}
		}


		return all_words;
	}

	@Override
	public String toString() {
		String txt = "";

		final int width = this.char_grid[0].length;
		final int height = this.char_grid.length;
		for (int i = 0; i < width; i++) {
			for (int j = 0; j < height; j++) {
				txt += this.char_grid[j][i]+"|";
			}
			txt += '\n';
		}

		return txt;
	}
}
